home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / util / time / NTPSync21.lha / NTPSync.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  7KB  |  224 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <netdb.h>
  9.  
  10. #include <clib/locale_protos.h>
  11. #include <devices/timer.h>
  12. #include <clib/timer_protos.h>
  13. #include <clib/exec_protos.h>
  14. #include <clib/alib_protos.h>
  15. #include <clib/locale_protos.h>
  16. #include <clib/macros.h>
  17.  
  18. #define NTP_PORT 123
  19.  
  20. UBYTE *version = "$VER: NTPSync 2.1 (20.1.98)";
  21.  
  22. struct Timestamp {
  23.   unsigned long seconds;
  24.   unsigned long fractions;
  25. };
  26.  
  27. struct ntp_message {
  28.   int LI       : 2;
  29.   int VN       : 3;
  30.   int Mode     : 3;
  31.   unsigned char Stratum;
  32.   unsigned char Poll;
  33.   unsigned char Precision;
  34.   long RootDelay;
  35.   long RootDispesion;
  36.   long ReferenceIdentifier;
  37.   struct Timestamp ReferenceTimestamp;
  38.   struct Timestamp OriginateTimestamp;
  39.   struct Timestamp ReceiveTimestamp;
  40.   struct Timestamp TransmitTimestamp;
  41. };
  42.  
  43. int UTCdiff;
  44.  
  45. /* Calculates dst = s1+s2 */
  46. void TSAdd(struct Timestamp *s1,struct Timestamp *s2, struct Timestamp *dst)
  47. {
  48.   dst->fractions = s1->fractions+s2->fractions;
  49.  
  50.   if(dst->fractions < MAX(s1->fractions,s2->fractions)) {
  51.     dst->seconds = s1->seconds + s2->seconds + 1;
  52.   } else 
  53.     dst->seconds = s1->seconds + s2->seconds;
  54. }
  55. /* Calculates dst = s1-s2 */
  56. void TSSub(struct Timestamp *s1,struct Timestamp *s2, struct Timestamp *dst)
  57. {
  58.   if(s1->fractions<s2->fractions) {
  59.     dst->seconds = s1->seconds - s2->seconds - 1;
  60.   } else {
  61.     dst->seconds = s1->seconds - s2->seconds;
  62.   }
  63.   dst->fractions = s1->fractions - s2->fractions;
  64. }
  65.  
  66. void Ami2NTP(struct timeval *tv,struct Timestamp *ts)
  67. {
  68.   ts->seconds = tv->tv_secs+2461449600-UTCdiff;
  69.   ts->fractions = (tv->tv_micro*4295)|1;
  70. }
  71. void NTP2Ami(struct timeval *tv,struct Timestamp *ts)
  72. {
  73.   tv->tv_secs = ts->seconds-2461449600+UTCdiff;
  74.   tv->tv_micro = ts->fractions/4295;
  75. }
  76.  
  77. struct timerequest *TimerIO;
  78. struct MsgPort *TimerMP;
  79. struct Message *TimerMSG;
  80.  
  81. struct Library *LocaleBase;
  82.  
  83. int main(int argc,char *argv[])
  84. {
  85.   int sockfd;
  86.   struct sockaddr_in serv_addr,cli_addr;
  87.   struct ntp_message msg;
  88.   struct hostent *hent;
  89.   int fromlen;
  90.   unsigned int ntpport;
  91.   char servername[80];
  92.   int retval=0;
  93.   int i;
  94.   struct Timestamp roundtrip;
  95.  
  96.   if(argc!=3 && argc!=2) {
  97.     printf("NTPSync <NTP server>[:port] [diff from UTC in minutes]\n");
  98.     exit(20);
  99.   }
  100.  
  101.   for(i=0;argv[1][i] && argv[1][i]!=':';i++) {
  102.     servername[i]=argv[1][i];
  103.   }
  104.   servername[i]=0;
  105.   if(argv[1][i]==':') {
  106.     ntpport=atoi(&argv[1][i+1]);
  107.   } else ntpport=NTP_PORT;
  108.  
  109.   if(!(hent=gethostbyname(servername))) {
  110.     printf("Can't resolve address %s!\n",argv[1]);
  111.     exit(15);
  112.   }
  113.  
  114.   bzero((char *)&serv_addr,sizeof(serv_addr));
  115.   serv_addr.sin_family      = AF_INET;
  116.   serv_addr.sin_addr        = *((struct in_addr *)hent->h_addr);
  117.   serv_addr.sin_port        = htons(ntpport);
  118.  
  119.   if(argc==3) {
  120.     UTCdiff = atoi(argv[2])*60;
  121.   } else {
  122.     struct Locale *locale;
  123.  
  124.     if(LocaleBase = OpenLibrary("locale.library",0)) {
  125.       if(locale = OpenLocale(NULL)) {
  126.         UTCdiff = -locale->loc_GMTOffset*60;
  127.         printf("UTC difference not given, locale.library told %d mins...\n",-locale->loc_GMTOffset);
  128.         CloseLocale(locale);
  129.       } else {
  130.         retval=11;
  131.         printf("Can't open locale!\n");
  132.       }
  133.       CloseLibrary(LocaleBase);
  134.     } else {
  135.       retval=12;
  136.       printf("Can't open locale.library!\n");
  137.     }
  138.     if(retval) return(retval);
  139.   }
  140.   if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
  141.     printf("Can't create socket!\n");
  142.     retval=10;
  143.   } else {
  144.     bzero((char *)&cli_addr,sizeof(cli_addr));
  145.     cli_addr.sin_family      = AF_INET;
  146.     cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  147.     cli_addr.sin_port        = htons(NTP_PORT);
  148.  
  149.     if(bind(sockfd, (struct sockaddr *) &cli_addr,sizeof(cli_addr)) < 0 ) {
  150.       cli_addr.sin_port        = htons(0);
  151.       if(bind(sockfd, (struct sockaddr *) &cli_addr,sizeof(cli_addr)) < 0 ) {
  152.         printf("Can't bind()!\n");
  153.         retval=9;
  154.       }
  155.     }
  156.     if(!retval) {
  157.       if(TimerMP = CreateMsgPort()) {
  158.         if(TimerIO = (struct timerequest *) CreateExtIO(TimerMP,sizeof(struct timerequest))) {
  159.           if(!(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0L))) {
  160.             bzero((char *)&msg,sizeof(struct ntp_message));
  161.             msg.LI = 0;
  162.             msg.Mode = 3;
  163.             msg.VN = 2;
  164.  
  165.             TimerIO->tr_node.io_Command = TR_GETSYSTIME;
  166.             DoIO((struct IORequest *) TimerIO);
  167.  
  168.             Ami2NTP(&TimerIO->tr_time,&msg.TransmitTimestamp);
  169.  
  170.             fromlen = sizeof(serv_addr);
  171.  
  172.             printf("Sending request...\n");
  173.             sendto(sockfd,(char *)&msg,sizeof(msg),0,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
  174.             TimerIO->tr_node.io_Command = TR_GETSYSTIME;
  175.             retval = recvfrom(sockfd,(char *)&msg,sizeof(msg),0,(struct sockaddr *)&serv_addr,(LONG *)&fromlen);
  176.  
  177.             if(retval>=sizeof(struct ntp_message) && msg.Mode==4 && msg.VN<5) {
  178.               if(msg.Mode==4 && msg.VN<5) {
  179.                 DoIO((struct IORequest *) TimerIO);
  180.  
  181.                 Ami2NTP(&TimerIO->tr_time,&roundtrip);
  182.  
  183.                 TSSub(&roundtrip,&msg.OriginateTimestamp,&roundtrip);
  184.                 TSSub(&msg.TransmitTimestamp,&msg.ReceiveTimestamp,&msg.ReferenceTimestamp);
  185.                 TSSub(&roundtrip,&msg.ReferenceTimestamp,&roundtrip);
  186.                 roundtrip.seconds = roundtrip.seconds / 2;
  187.                 roundtrip.fractions = roundtrip.fractions / 2;
  188.                 TSAdd(&roundtrip,&msg.TransmitTimestamp,&msg.TransmitTimestamp);
  189.  
  190.                 NTP2Ami(&TimerIO->tr_time,&msg.TransmitTimestamp);
  191.                 TimerIO->tr_node.io_Command = TR_SETSYSTIME;
  192.                 DoIO((struct IORequest *) TimerIO);
  193.  
  194.                 TimerIO->tr_time.tv_secs = roundtrip.seconds;
  195.                 TimerIO->tr_time.tv_micro = roundtrip.fractions/4295;
  196.  
  197.                 printf("Time set according to %s (Stratum %d, roundtrip delay %d µs)!\n",argv[1],msg.Stratum,TimerIO->tr_time.tv_secs*100000+TimerIO->tr_time.tv_micro);
  198.               }
  199.               retval=0;
  200.             } else {
  201.               printf("Invalid reply got from server (or error while receiving), time not set!\n");
  202.               retval=5;
  203.             }
  204.             CloseDevice((struct IORequest *)TimerIO);
  205.           } else {
  206.             printf("Error in allocating resources!\n");
  207.             retval=6;
  208.           }
  209.           DeleteExtIO((struct IORequest *)TimerIO);
  210.         } else {
  211.           printf("Error in allocating resources!\n");
  212.           retval=7;
  213.         }
  214.         DeleteMsgPort(TimerMP);
  215.       } else {
  216.         printf("Error in allocating resources!\n");
  217.         retval=8;
  218.       }
  219.     }
  220.     CloseSocket(sockfd);
  221.   }
  222.   return(retval);
  223. }
  224.